/*************************************************************************
	> File Name: 007.实现智能指针对象.cpp
	> Author: Maureen 
	> Mail: Maureen@qq.com 
	> Created Time: 五  1/ 7 11:13:14 2022
 ************************************************************************/

#include <iostream>
using namespace std;

namespace maureen {
    class A {
    public:
        A() { cout << "default ctor" << endl; }
            
        ~A() { cout << "dtor" << endl; }
        
        int x, y;
    };

    class shared_ptr {
    public: 
        //默认构造函数
        shared_ptr();
        //转换构造函数
        shared_ptr(A*);
        //拷贝构造函数
        shared_ptr(const shared_ptr&);
        //统计引用计数
        int use_count();
        //重载->
        A* operator->();
        //重载*
        A& operator*();
        //重载赋值运算符
        shared_ptr& operator=(const shared_ptr&);
        //析构函数
        ~shared_ptr();
    private:
        void decrease_by_one();
        void increase_by_one();
        int *cnt;//引用计数
        A* obj;
    };

    shared_ptr::shared_ptr() : cnt(nullptr), obj(nullptr) {  }

    shared_ptr::shared_ptr(A* obj) : obj(obj), cnt(new int(1)) {   }

    shared_ptr::shared_ptr(const shared_ptr& p) : cnt(p.cnt), obj(p.obj) { *p.cnt += 1; }

    int shared_ptr::use_count() { return cnt ? *cnt : 0; }

    A* shared_ptr::operator->() { return obj; }

    A& shared_ptr::operator*() { return *obj; }

    void shared_ptr::decrease_by_one() {
        if (this->cnt != nullptr) {
            *(this->cnt) -= 1;
            if (*(this->cnt) == 0) {
                delete this->obj;
                delete this->cnt;
            }
        }
        return ;
    }

    void shared_ptr::increase_by_one() {
        if (cnt != nullptr) {
            *cnt += 1;
        }
        return ;
    }
    
    shared_ptr::~shared_ptr() {
        this->decrease_by_one();
        this->obj = nullptr;
        this->cnt = nullptr;
    }

    shared_ptr& shared_ptr::operator=(const shared_ptr& rhs) {
        if (this->obj != rhs.obj) { //判断是否指向同一个对象
            decrease_by_one(); //引用计数-1
            obj = rhs.obj;
            cnt = rhs.cnt;
            increase_by_one(); //引用计数+1
        }
        return *this;
    }
} //end of maureen 

int main() {
    maureen::A* p1 = new maureen::A();
    p1 = nullptr;

    maureen::shared_ptr p2(new maureen::A()); //p2是智能指针对象
    cout << p2.use_count() << endl; //1

    maureen::shared_ptr p3 = p2;
    p2->x = 123;
    p2->y = 456;
    (*p2).x = 456;
    cout << p2.use_count() << endl; //2
    p2 = nullptr; //自动析构

    cout << p3.use_count() << endl; //1
    p2 = p3;

    cout << p2.use_count() << endl; //2
    return 0;
}

//运行结果:
//default ctor
//default ctor
//1
//2
//1
//2
//dtor
